/**
 * 泛型：指在定义函数。接口或类的时候，不预先指定具体的类型，而是在使用的时候在指定类型的一种特性
 */
function funcTo1<T> (a:T, b:T){
  return {a,b}
}

funcTo1("ASd",1)
funcTo1(1,"SD")
funcTo1(true,"SD")

let d:object={
  dsa:"sd"
}
funcTo1(d,"sda")

let xTo1 = ()=>{
}
funcTo1(xTo1,"Dsa")

let arr = [1,"SE"]
funcTo1(arr,"das")
funcTo1([1,"SD"],"SDad") //???

function loggingIdentity <Type>(arg:Type):Type{
  if(typeof arg === "number"){
    console.log(arg.length); //类型“Type”上不存在属性“length”
  }
  return arg
}


function loggingIdentityTo1 <Type>(arg:Array<Type>):Type[]{
  
  console.log(arg.length); //类型“Type”上不存在属性“length”
  return arg
}
loggingIdentityTo1(["asdad"])

/**
 * 泛型类型
 */

function identity<A>(arg:A):A{
    return arg
}
let myIdentity: <A>(arg:A)=> A = identity

//调用签名的对象字面量来定义泛型函数   调用签名
function identityTo1<T>(arg: T): T {
  return arg;
}

let myIdentityTo1: {<T>(arg: T): T} = identity;

// 泛型接口
interface GenericIdentityFn {
  <T>(arg:T):T
}
let myIdentityTo2:GenericIdentityFn = identity

interface GenericIdentityFnTo1 <T>{
  (arg:T):T
}
let myIdentityTo3:GenericIdentityFnTo1<number> = identity;

/**
 * 泛型类
 */

class GenericNumber<T>{
  zeroValue:T | undefined,
  add:((x: T, y: T) => T) | undefined
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function(x, y) { return x + y; };

console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));

/**
 * 泛型约束
 */

interface Lengthwise {
  length: number;
}

function loggingIdentityTo2<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);  // Now we know it has a .length property, so no more error
  return arg;
}

loggingIdentityTo2(3);   //类型“number”的参数不能赋给类型“Lengthwise”的参数。
loggingIdentityTo2({length: 10, value: 3});